package com.cmw.core.util;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.HttpURLConnection;
import java.net.URL;
import java.nio.charset.Charset;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;

import com.cmw.core.kit.file.FileUtil;
import org.apache.http.Consts;
import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicNameValuePair;
import org.apache.log4j.Logger;

import com.alibaba.fastjson.JSONObject;


/**
 * Http 工具类
 * 
 * @author	chengmingwei
 * @date	2015年3月4日 下午2:20:11
 */
public class HttpUtil {
	/** 
     * 日志 
     */  
    private static final Logger LOGGER = Logger.getLogger(HttpUtil.class);
	
	
	public static void main(String[] args) {
//		HttpPost postObj = new HttpPost("http://localhost:8080/wechat_demo/pages/login.jsp");
	//	HttpClient httpClient = new HttpClient("", "", "");
		/*------- 获取 Access_Token CODE START ---------*/
		
//		String APPID = "wx8a27ac6ecdbc8ec2";
//		String APPSECRET = "1715e47e6c02be68c7638151551fae38";
//		String url = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid={APPID}&secret={APPSECRET}";
//		url = url.replace("{APPID}", APPID).replace("{APPSECRET}", APPSECRET);
//		String content = request(url);
//		System.out.println(content);
		
		/*------- 获取 Access_Token CODE END ---------*/
		String access_token = "0x8zeAPwUqWc9Wz9tqRzqhevYNxzqnal9lVdc0LtF4M_u4yagg4OX1RR78GrvrYPwXc54y9eu1JCa1bf41m2Lt7s-AaL0QGeafrxFvMILzQ";
//		//查询自定义菜单的接口
		String getall_menus_url = "https://api.weixin.qq.com/cgi-bin/menu/get?access_token={ACCESS_TOKEN}";
		getall_menus_url = getall_menus_url.replace("{ACCESS_TOKEN}", access_token);
		String menusContent = request(getall_menus_url);
		System.out.println(menusContent);
		
		//删除自定义菜单的接口
//		String del_menus_url = "https://api.weixin.qq.com/cgi-bin/menu/delete?access_token={ACCESS_TOKEN}";
//		 del_menus_url = del_menus_url.replace("{ACCESS_TOKEN}", access_token);
//		 String del_menusContent = request(del_menus_url);
//		 System.out.println(del_menusContent);
		 
		//创建自定义菜单的接口
//		String add_menus_url = "https://api.weixin.qq.com/cgi-bin/menu/create?access_token={ACCESS_TOKEN}";
//		add_menus_url = add_menus_url.replace("{ACCESS_TOKEN}", access_token);
//		String menuDatas = FileUtil.ReadFileToStr("/Users/chenjin/Documents/my_works/njj_dev/wechat_demo/resources/wechat_menus.json");
//		String menusResult = request(add_menus_url,METHOD_POST,menuDatas,"utf-8");
//		System.out.println(menusResult);
	}
	
	
	/**
	 * 将 json 字符串内容提交到服务器
	 * @param url	服务器URL
	 * @param method	提交方式 [post 或 get]
	 * @param content	json 字符串内容
	 * @return 返回服务器响应内容字符串
	 * @author chengmingwei
	 * @date 2015年3月4日 下午4:54:24
	 */
	public static String requestJson(String url, String method, String content){
		String encoding = "utf-8";
		StringEntity entity = getStringEntity(content,encoding);
		entity.setContentType("application/json");
		return request(url,method,encoding,entity);
	}
	
	/**
	 * 将字符串实体对象提交到服务器
	 * @param url	服务器URL
	 * @param method	提交方式 [post 或 get]
	 * @param encoding 编码方式 [utf-8,gb2312 等等]
	 * @param strEntity	StringEntity 字符串对象
	 * @return 返回服务器响应内容字符串
	 * @author chengmingwei
	 * @date 2015年3月4日 下午4:54:24
	 */
	public static String request(String url, String method, String encoding, Map<String,Object> datas){
		if(!StringHandler.isValidStr(url)) throw new RuntimeException("参数：url 不能为空!");
		if(!StringHandler.isValidStr(method)) throw new RuntimeException("参数：method 不能为空!");
		if(null == datas || datas.size() <= 0) throw new RuntimeException("参数：datas 不能为空!");
		String content = null;
		
		if(METHOD_POST.equals(METHOD_POST)){/*post 提交方式*/
			HttpPost httpPost = new HttpPost(url);
			UrlEncodedFormEntity entity = getFormEntityByMap(datas,Consts.UTF_8);
			httpPost.setEntity(entity);
			content = request(encoding, httpPost);
		}else{/* get 提交方式*/
			HttpGet httpGet = new HttpGet(url);
			content = request(encoding, httpGet);
		}
		return content;
	}
	
	/**
	 * 通过 get 方式从服务器上获取内容
	 * @param url	服务器URL
	 * @return 返回服务器响应内容字符串
	 * @author chengmingwei
	 * @date 2015年3月4日 下午4:54:24
	 */
	public static String request(String url){
		if(!StringHandler.isValidStr(url)) throw new RuntimeException("参数：url 不能为空!");
		String content = null;
		String encoding = "utf-8";
		/* get 提交方式*/
		HttpGet httpGet = new HttpGet(url);
		content = request(encoding, httpGet);
		return content;
	}
	
	/**
	 * Post提交请求
	 * @param url	url地址
	 * @param datas	提交数据
	 * @return	返回提交后的响应内容
	 */
	public static String post(String url, Map<String,Object> datas){
		return request(url, METHOD_POST, datas);
	}
	
	/**
	 * Post提交请求
	 * @param url	url地址
	 * @return	返回提交后的响应内容
	 */
	public static String post(String url){
		return request(url, METHOD_POST, null);
	}
	
	/**
	 * Get提交请求
	 * @param url	url地址
	 * @param datas	请求参数数据
	 * @return	返回提交后的响应内容
	 */
	public static String get(String url, Map<String,Object> datas){
		return request(url, METHOD_GET, datas);
	}
	
	/**
	 * Get提交请求
	 * @param url	url地址
	 * @return	返回提交后的响应内容
	 */
	public static String get(String url){
		return request(url, METHOD_GET, null);
	}
	
	
	/**
	 * 将字符串实体对象提交到服务器
	 * @param url	服务器URL
	 * @param method	提交方式 [post 或 get]
	 * @param encoding 编码方式 [utf-8,gb2312 等等]
	 * @param strEntity	StringEntity 字符串对象
	 * @return 返回服务器响应内容字符串
	 * @author chengmingwei
	 * @date 2015年3月4日 下午4:54:24
	 */
	public static String request(String url, String method, Map<String,Object> datas){
		if(!StringHandler.isValidStr(url)) throw new RuntimeException("参数：url 不能为空!");
		if(!StringHandler.isValidStr(method)) throw new RuntimeException("参数：method 不能为空!");
		if(null == datas || datas.size() <= 0) throw new RuntimeException("参数：datas 不能为空!");
		String content = null;
		String encoding = "utf-8";
		if(method.equals(METHOD_POST)){/*post 提交方式*/
			HttpPost httpPost = new HttpPost(url);
			if(null != datas && datas.size() > 0){
				UrlEncodedFormEntity entity = getFormEntityByMap(datas);
				httpPost.setEntity(entity);
			}
			content = request(encoding, httpPost);
		}else{/* get 提交方式*/
			if(null != datas && datas.size() > 0){
				url = bindPars2url(url, datas);
			}
			HttpGet httpGet = new HttpGet(url);
			content = request(encoding, httpGet);
		}
		return content;
	}
	
	/**
	 * 将请求参数绑定到URL上
	 * @param url	url 地址
	 * @param datas	要绑定的参数
	 * @return	返回绑定了参数的URL字符串
	 * @author chengmingwei
	 * @date 2015年3月4日 下午7:14:39
	 */
	private static String bindPars2url(String url, Map<String,Object> datas){
		char sigin = '&';
		if(-1 == url.indexOf("?")){
			sigin = '?';
		}
		StringBuilder sbPars = new StringBuilder();
		Set<String> keys = datas.keySet();
		int i = 0;
		for(String key : keys){
			Object val = datas.get(key);
			if(null == val) val = "";
			sbPars.append(key).append("=").append(val);
			if (i != keys.size() - 1)
			{
				sbPars.append('&');
			}
			i++;
		}
		String parsStr = StringHandler.RemoveStr(sbPars.toString(), sigin+"");
		url += sigin+parsStr;
		return url;
	}
	
	private static UrlEncodedFormEntity getFormEntityByMap(Map<String,Object> datas){
		return getFormEntityByMap(datas,Consts.UTF_8);
	}
	
	
	private static UrlEncodedFormEntity getFormEntityByMap(Map<String,Object> datas,Charset encoding){
		List<NameValuePair> formparams = new ArrayList<NameValuePair>();
		Set<String> keys = datas.keySet();
		for(String key : keys){
			Object val = datas.get(key);
			if(null == val) val = "";
			NameValuePair nvPair = new BasicNameValuePair(key,val.toString());
			formparams.add(nvPair);
		}
		UrlEncodedFormEntity entity = new UrlEncodedFormEntity(formparams, encoding);
		return entity;
	}
	
	/**
	 * 将字符串实体对象提交到服务器
	 * @param url	服务器URL
	 * @param method	提交方式 [post 或 get]
	 * @param encoding 编码方式 [utf-8,gb2312 等等]
	 * @param strEntity	StringEntity 字符串对象
	 * @return 返回服务器响应内容字符串
	 * @author chengmingwei
	 * @date 2015年3月4日 下午4:54:24
	 */
	public static String request(String url, String method, String encoding, StringEntity strEntity){
		if(!StringHandler.isValidStr(url)) throw new RuntimeException("参数：url 不能为空!");
		if(!StringHandler.isValidStr(method)) throw new RuntimeException("参数：method 不能为空!");
		if(null == strEntity) throw new RuntimeException("参数：strEntity 不能为空!");
		String content = null;

		if(METHOD_POST.equals(method)){/*post 提交方式*/
			HttpPost httpPost = new HttpPost(url);
			httpPost.setEntity(strEntity);
			content = request(encoding, httpPost);
			httpPost.abort();
		}else{/* get 提交方式*/
			HttpGet httpGet = new HttpGet(url);
			content = request(encoding, httpGet);
			httpGet.abort();
		}
		return content;
	}

	/**
	 * 将字符串实体对象提交到服务器
	 * @param encoding 编码方式 [utf-8,gb2312 等等]
	 * @param request  请求对象
	 * @return 返回服务器响应内容字符串
	 * @author chengmingwei
	 * @date 2015年3月4日 下午4:54:24
	 */
	private static String request(String encoding,HttpUriRequest request) {
		String content = null;
		CloseableHttpClient httpClient = HttpClients.createDefault();
		try {
			CloseableHttpResponse response= httpClient.execute(request);
			HttpEntity respEntity = response.getEntity();
			if(null == respEntity) return null;
			InputStream ins = respEntity.getContent();
			content = FileUtil.getContentByInputStream(ins, encoding);
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return content;
	}


	/**
	 * 将字符串内容提交到服务器
	 * @param url	服务器URL
	 * @param method	提交方式 [post 或 get]
	 * @param content	字符串内容
	 * @param encoding	字符串编码
	 * @return 返回服务器响应内容字符串
	 * @author chengmingwei
	 * @date 2015年3月4日 下午4:54:24
	 */
	public static String request(String url, String method, String content, String encoding){
		StringEntity strEntity = getStringEntity(content, encoding);
		return request(url,method,encoding,strEntity);
	}
	
	/**
	 * 获取 StringEntity 对象
	 * @param content	字符串内容
	 * @param encoding	编码
	 * @return	返回 StringEntity 对象
	 * @author chengmingwei
	 * @date 2015年3月4日 下午3:44:24
	 */
	private static StringEntity getStringEntity(String content ,String encoding){
		StringEntity strEntity = new StringEntity(content, encoding);
		strEntity.setContentEncoding(encoding.toUpperCase());
		return strEntity;
	}
	
	/**
	 * 发送请求 ,返回请求结果
	 */
	public static String http(String url, Map<String, String> params) {
		URL u = null;
		HttpURLConnection con = null;
		String cmdId = params.get("CmdId");
		LOGGER.info("\n========== "+cmdId+" [START] ===========");
		StringBuilder sbLog = new StringBuilder();
		// 构建请求参数
		StringBuffer sb = new StringBuffer();
		if (params != null) {
			for (Entry<String, String> e : params.entrySet()) {
				sb.append(e.getKey());
				sb.append("=");
				sb.append(e.getValue());
				sb.append("&");
				sbLog.append(e.getKey() + " : " + e.getValue()+"\n");
			}
			sb.deleteCharAt(sb.length() - 1);
			LOGGER.info(sbLog.toString());
		}
		// 发送请求
		try {
			u = new URL(url);
			con = (HttpURLConnection) u.openConnection();
			con.setRequestMethod("POST");
			con.setDoOutput(true);
			con.setDoInput(true);
			con.setUseCaches(false);
			con.setRequestProperty("Content-Type", "application/x-www-form-urlencoded;charset=utf-8");
			OutputStreamWriter osw = new OutputStreamWriter(con.getOutputStream(), "utf-8");
			osw.write(sb.toString());
			osw.flush();
			osw.close();
		} catch (Exception e) {
			e.printStackTrace();
		} finally {
			if (con != null) {
				con.disconnect();
			}
		}

		// 读取返回内容
		StringBuffer buffer = new StringBuffer();
		try {
			BufferedReader br = new BufferedReader(new InputStreamReader(con.getInputStream(), "UTF-8"));
			String temp;
			while ((temp = br.readLine()) != null) {
				buffer.append(temp);
			}
		} catch (Exception e) {
			e.printStackTrace();
		}
		JSONObject json = null;
		try {
			String returnContent = buffer.toString();
			LOGGER.info("======== 汇付应答报文 START CODE =========\n");
			LOGGER.info(returnContent);
			LOGGER.info("======== 汇付应答报文 START END =========\n");
 			json = JSONObject.parseObject(returnContent);
		} catch (Exception e) {
			json = new JSONObject();
			json.put("RespCode", -10000);
			String str = buffer.toString();
			try {
				int index = 0;
				if(str.contains("<p class=\"title\">")){
					str = str.substring(str.indexOf("<p class=\"title\">")+17);
					index = str.indexOf("</p>");
					str = str.substring(0, index);
				}else if (str.contains("<p class=\"desc\">")){
					str = str.substring(str.indexOf("<p class=\"desc\">") + 17);
					index = str.indexOf("</p>");
					str = str.substring(0, index);
				}
			} catch (Exception ee) {
				str = "系统异常";
			}
			json.put("RespDesc", "汇付返回结果:"+str);
		}
		LOGGER.info("========== "+cmdId+" [END] ===========\n");
		return json.toString();
	}
	
	
	/**
	 * HTTP 提交方式 "post"
	 */
	public static final String METHOD_POST = "post";
	/**
	 * HTTP 提交方式 "get"
	 */
	public static final String METHOD_GET = "get";
}
